package com.ymt.bpm.engine.handler.process.impl;

import com.alibaba.fastjson.JSONObject;
import com.ymt.bpm.dao.MDao;
import com.ymt.bpm.dao.Mapper;
import com.ymt.bpm.engine.EngineConst;
import com.ymt.bpm.engine.bpmn.ProcessUtil;
import com.ymt.bpm.engine.handler.process.ProcessExcutionHandler;
import com.ymt.bpm.model.PPi;
import com.ymt.bpm.model.PPiHi;
import com.ymt.bpm.model.PUserRef;
import com.ymt.bpm.service.engine.bpd.BpdVersionCacheService;
import com.ymt.bpm.util.Const;
import com.ymt.bpm.util.DateUtil;
import org.activiti.engine.delegate.DelegateExecution;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by Johnny on 2016/12/24.
 */
@Component
public class ProcessExcutionHandlerImpl implements ProcessExcutionHandler {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private MDao dao;

    @Autowired
    private BpdVersionCacheService bvcs;

    @Override
    public void onProcessStart(DelegateExecution execution) {
        if (log.isDebugEnabled()) {
            log.debug("onProcessStart...");
        }
        String tenantId = execution.getTenantId();
        if (tenantId==null || tenantId.length()==0) {
            tenantId = execution.getVariable(Const.TENANT_ID, String.class);
        }

        //set piEid
        execution.setVariable(EngineConst.PV_PIEID, execution.getProcessInstanceId());

        String isCallActivity = execution.getVariable(EngineConst.PV_IS_CALLACTIVITY, String.class);
        String callActivityId = null;
        if ("true".equals(isCallActivity)) { //子流程
            callActivityId = execution.getVariable(EngineConst.PV_CALLACTIVITY_ID, String.class);
            String parentPiEid = execution.getVariable(EngineConst.PV_PARENT_PIEID, String.class);
            PPi parentPi = new PPi();
            PPi pi = new PPi();
            PUserRef piUserRef = new PUserRef();
            if (tenantId!=null && tenantId.length()>0 && StringUtils.isNumeric(tenantId)) {
                parentPi.setTenantId(Integer.parseInt(tenantId));
                pi.setTenantId(parentPi.getTenantId());
                piUserRef.setTenantId(Integer.parseInt(tenantId));
            }
            parentPi.setPiEid(parentPiEid);
            //取得父级流程
            parentPi = dao.selectOne(Mapper.PPiMapper, "selectByObj", parentPi);
            //取得版本
            JSONObject engVersionMap = bvcs.selectBpdDefById(tenantId, execution.getProcessDefinitionId());
            String bpdId = engVersionMap.getString("key");
            int versionid = engVersionMap.getInteger("version");
            JSONObject version = bvcs.getVersionJson(tenantId, bpdId, versionid);
            JSONObject bpmnConfig = version.getJSONObject(EngineConst.BPMNCONF);

            //set value
            pi.setPiEid(execution.getProcessInstanceId());
            pi.setPiId(parentPi.getPiId());
            pi.setVersionid(versionid);
            pi.setBpdId(bpdId);
            pi.setBpdName(engVersionMap.getString("name"));
            pi.setUserId(parentPi.getUserId());
            pi.setUserName(parentPi.getUserName());
            pi.setStatus(PPi.PI_STATUS_ACTIVE);
            pi.setCreateTime(DateUtil.getGMTDate());
            //pi.setBizId(null);
            pi.setDueTime(ProcessUtil.getPiDueTimeFromNow(bpmnConfig));
//          pi.setBizNo(null);
            pi.setTitle(parentPi.getTitle());
//        pi.setSummary(null);
            pi.setParentPieid(parentPiEid);
            pi.setCallActivityId(callActivityId);
            dao.insert(Mapper.PPiMapper, "insertSelective", pi);

            //用户引用
            piUserRef.setId(parentPiEid);
            piUserRef.setType(PUserRef.TYPE_PROCESS);
            piUserRef.setUserId(parentPi.getUserId());
            piUserRef = dao.selectOne(Mapper.PUserRefMapper, "selectByPrimaryKey", piUserRef);
            //插入新的
            piUserRef.setId(pi.getPiEid());
            dao.insert(Mapper.PUserRefMapper, "insertSelective", piUserRef);

            //映射子流程自父流程的输入
            //先获取父流程变量和版本信息
            JSONObject parentVersion = bvcs.getVersionJson(tenantId, parentPi.getBpdId(), parentPi.getVersionid());
            JSONObject parentProcessVar = execution.getEngineServices().getRuntimeService().getVariable(parentPiEid, EngineConst.PROCESSVAR, JSONObject.class);
            JSONObject subInput = ProcessUtil.mappingProcessVarToBizVar(callActivityId, parentVersion.getJSONObject(EngineConst.BPMNCONF), parentProcessVar);
            subInput = ProcessUtil.toFlatVariables(subInput);
            JSONObject variables = ProcessUtil.generateProcessVarialbes(bpmnConfig, subInput);
            JSONObject processVar = new JSONObject();
            processVar.put(EngineConst.VARIABLES, variables);
            execution.setVariable(EngineConst.PROCESSVAR, processVar);

        } else {    //主流程

        }

        //主子流程跳转处理
        String skipTo = execution.getVariable(EngineConst.PV_SKIP_TO, String.class);
        if(skipTo!=null && skipTo.length()>0){
            ProcessUtil.skipTo(execution, skipTo);
        }
    }

    @Override
    public void onProcessTake(DelegateExecution execution) {
        if (log.isDebugEnabled()) {
            log.debug("onProcessTake...");
        }
    }

    @Override
    public void onProcessComplete(DelegateExecution execution) {
        if (log.isDebugEnabled()) {
            log.debug("onProcessComplete...");
        }
        //pis to his
        String tenantId = execution.getVariable(Const.TENANT_ID, String.class);
        PPi key = new PPi();
        if (tenantId!=null && tenantId.length()>0 && StringUtils.isNumeric(tenantId)) {
            key.setTenantId(Integer.parseInt(tenantId));
        }
        key.setPiEid(execution.getProcessInstanceId());
        PPi pi = dao.selectOne(Mapper.PPiMapper, "selectByObj", key);
        if (pi==null) { //终止流程操作，这里pi已经不存在了
            return;
        }

        Date now = DateUtil.getGMTDate();
        PPiHi hi = new PPiHi();
        hi.setTenantId(pi.getTenantId());
        hi.setPiEid(pi.getPiEid());
        hi.setPiId(pi.getPiId());
        hi.setVersionid(pi.getVersionid());
        hi.setBizId(pi.getBizId());
        hi.setBpdId(pi.getBpdId());
        hi.setBpdName(pi.getBpdName());
        hi.setUserId(pi.getUserId());
        hi.setUserName(pi.getUserName());
        hi.setParentPieid(pi.getParentPieid());
        hi.setStatus(PPiHi.STATUS_COMPLETE);
        hi.setCreateTime(pi.getCreateTime());
        hi.setCompleteDate(now);
        hi.setDueTime(pi.getDueTime());
        hi.setDeleteReason("COMPLETE"); //TODO
        hi.setDuration(new Long(now.getTime() - pi.getCreateTime().getTime()).intValue());
        //hi.setStartActId(); //TODO
        //hi.setEndActId();
        hi.setBizNo(pi.getBizNo());
        hi.setTitle(pi.getTitle());
        hi.setSummary(pi.getSummary());
        hi.setCallActivityId(pi.getCallActivityId());

        dao.delete(Mapper.PPiMapper, "deleteByObj", key);
        dao.insert(Mapper.PPiHiMapper, "insertSelective", hi);
    }

    /*@Override
    public void handle(ActivitiEvent event) {
        switch (event.getType()) {
            case ActivitiEventType.PROCESS_STARTED:
                ActivitiProcessStartedEvent apse = (ActivitiProcessStartedEvent) event;
                onProcessStarted(apse);
                break;
            case ActivitiEventType.PROCESS_COMPLETED:
                onProcessComplete(event);
                break;
            default:
                //do nothing
        }
    }*/

}
